<!-- 系统运行趋势分析 -->
<template>
	<div class="ywgzt-container">
		<title-banner title="系统运行趋势分析" :noBack="true"></title-banner>
		<div class="content">
			<yd-form ref="myForm" :options="formOptions" :model="formData" :btns="formBtns"></yd-form>
			<div class="bg-box chart-box">
				<div class="trend-toggle-row">
					<span class="trend-title">时间窗口&nbsp;&nbsp;</span>
					<el-select v-model="routeParams.trendType" popper-class="ywgzt-select" size="small" @change="toggleTrendScale">
						<el-option v-for="option in trendOptions" :key="option.value" :value="option.value" :label="option.label"></el-option>
					</el-select>
				</div>
				<div id="sysTrendChart" class="chart-style"></div>
			</div>
			<div class="bg-box">
				<div class="table-title">
					<div class="circle"></div>
					<span class="title-label">增量比TOP10业务总览（{{ routeParams.tableStartTime }}-{{ routeParams.tableEndTime }}）</span>
				</div>
				<yd-table
					:formData="formData"
					:tableConfig="tableConfig"
					:tableData="tableData"
					@sizeChangeHandler="getTableData"
					@currentChangeHandler="getTableData"
					@sortChangeHandler="getTableData"
				></yd-table>
			</div>
		</div>
	</div>
</template>

<script setup name="OperateTrendAnalysis" lang="ts">
import * as echarts from 'echarts';
import { toDecimalFormate, parseTime } from '@/utils/common';
import { getAreaStyle, getTrendTimeRange } from '@/utils/ops-workbench/chartCommon';
import { queryCompleteAlarmTrend } from '@/api/ops-workbench/index';
import { queryIncrementRatioList } from '@/api/ops-workbench/system/operateTrendAnalysis';
import useShareYwgztDataStore from '@/store/ops-workbench/shareYwgztData';
import TitleBanner from '@/views/ops-workbench/components/TitleBanner/index.vue';
import { onActivated, onDeactivated, reactive, ref, computed, onMounted, onUnmounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import useCurrentInstance from '@/utils/useCurrentInstance';

const route = useRoute();
const router = useRouter();
const { proxy } = useCurrentInstance();
const shareDataStore = useShareYwgztDataStore();

type ApiVal = string | number | null | undefined;
interface RouteParams {
	[key: string]: any;
	trendType: number;
}

let routeParams = reactive<anyObj>({
	...route.query,
	trendType: parseInt(route.query.trendType as string),
});
let sysTrendChart: anyObj;
const formOptions = reactive<FormOptionType>([
	{
		type: 'select',
		label: '业务系统',
		prop: 'systemId',
		selectKey: 'value',
		api: {
			name: 'queryAppSystemOptions',
			params: { isStatus: 1 },
		},
	},
]);
const formBtns = reactive<BtnType[]>([
	{
		type: 'primary',
		text: '查询',
		handler: handleSearch,
	},
]);
// 时间下拉选项
const trendOptions = ref([
	{ label: '1小时', value: 1 },
	{ label: '4小时', value: 4 },
	{ label: '8小时', value: 8 },
	{ label: '12小时', value: 12 },
	{ label: '当天', value: 2 },
]);
const firstRender = ref(true);
// 上一次刷选中的时间区间
const lastTimeRange = reactive({
	startTime: '',
	endTime: '',
});
const lastTrendType = ref(route.query.trendType as string);
// 趋势图自动刷新定时器
const refreshChart = ref<NodeJS.Timer>();
// 趋势图刻度
const trendScale = ref(10);
// 表单数据
let formData = reactive<anyObj>({
	systemId: route.query.systemId,
});
const tableConfig = reactive({
	columns: [
		{
			label: '业务名称',
			prop: 'businessName',
		},
		{
			label: '增量比',
			prop: 'incrementRatio',
			formatter: (row: anyObj, val: ApiVal) => {
				if (val !== '' && val !== undefined && val !== null) {
					return val + '%';
				}
				return val;
			},
			sortable: true,
		},
		{
			label: '访问量',
			prop: 'visitCount',
			sortable: true,
		},
		{
			label: '交易量',
			prop: 'completeVisitCount',
			sortable: true,
		},
		{
			label: '平均响应耗时',
			prop: 'avgResponseTime',
			formatter(row: anyObj, val: ApiVal) {
				return toDecimalFormate(val, 'wm');
			},
			sortable: true,
		},
		{
			label: '失败数',
			prop: 'failVisitCount',
			sortable: true,
		},
		{
			label: '告警数',
			prop: 'alarmVisitCount',
			sortable: true,
		},
		{
			label: '成功率',
			prop: 'successRate',
			formatter: (row: anyObj, val: ApiVal) => {
				if (val !== '' && val !== undefined && val !== null) {
					return val + '%';
				}
				return val;
			},
			sortable: true,
		},
		{
			label: '健康度',
			prop: 'healthRate',
			formatter: (row: anyObj, val: ApiVal) => {
				if (val !== '' && val !== undefined && val !== null) {
					return val + '%';
				}
				return val;
			},
			sortable: true,
		},
		{
			label: '操作',
			prop: '',
			width: 100,
			operation: [
				{
					text: '详情',
					handler: (scope: anyObj) => goToBusiDetail(scope.row),
				},
			],
		},
	],
	pagination: {
		isAsc: 'desc',
		orderByColumn: 'incrementRatio',
		pageNum: 1,
		pageSIze: 10,
		total: 0,
	},
	loading: true,
});
const tableData = ref([]);
const currentDate = ref(new Date());
const ywgztSysShare = computed(() => shareDataStore.sysShare);

onMounted(() => {
	window.addEventListener('resize', chartResize);
	// 初始化图表对象
	initChart();
	handleSearch();
});
onUnmounted(() => {
	window.removeEventListener('resize', chartResize);
	// 销毁resize监听器
	clearStore();
	stopRefreshInterval();
});
onActivated(() => {
	window.addEventListener('resize', chartResize);
	// 添加resize监听器,自适应图表大小
	routeParams.trendType = parseInt(route.query.trendType as string);
	formData.systemId = route.query.systemId;
	routeParams.tableStartTime = route.query.tableStartTime;
	routeParams.tableEndTime = route.query.tableEndTime;

	// 初始化图表对象
	initChart();
	handleSearch();
});
onDeactivated(() => {
	window.removeEventListener('resize', chartResize);
	// 销毁resize监听器
	clearStore();
	stopRefreshInterval();
});
function handleSearch() {
	// 因为在跳转过来时附带了系统参数值,引起了表单条件改变,所以初进页面会触发一次handleSearch
	// routeParams = {
	// 	endTime: route.query.endTime,
	// 	startTime: route.query.startTime,
	// 	trendType: parseInt(route.query.trendType as string),
	// 	systemId: route.query.systemId,
	// };
	if (firstRender.value) {
		renderChart(true, ywgztSysShare.value);
	} else {
		getTableData();
		getChartData();
	}
}
function initChart() {
	sysTrendChart = echarts.init(document.getElementById('sysTrendChart')!);
}
function chartResize() {
	sysTrendChart.resize();
}
// 清除store数据
function clearStore() {
	shareDataStore.deleteYwgztSysShare();
}
// 切换趋势图的显示时间范围
function toggleTrendScale(val: number) {
	console.log(routeParams.trendType);
	// 上一次选中的时间类型
	let t = lastTrendType.value === '2' ? 24 : Number(lastTrendType.value);
	val = val === 2 ? 24 : val;
	if (val < t) {
		// 从大到小,取消选框
		sysTrendChart.dispatchAction({
			type: 'brush',
			areas: [],
		});
	} else {
		// 从小到大,仍框选那个时间范围
		firstRender.value = true;
	}
	lastTrendType.value = routeParams.trendType + '';
	getChartData();
}
// 请求趋势图数据
function getChartData() {
	let ltFlag = true;
	const d = {
		systemId: formData.systemId,
	};
	getTrendTimeRange(routeParams.trendType, d);
	queryCompleteAlarmTrend(d).then((res: ApiResponse) => {
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		const resData = res.data;
		if (!resData || resData.length <= 0) {
			// 无数据
			sysTrendChart.clear();
			sysTrendChart.setOption({
				title: {
					text: '暂无数据',
					x: 'center',
					y: 'center',
					textStyle: {
						color: '#ffffff70',
					},
				},
			});
			ltFlag = false;
			renderChart(ltFlag, {
				labelTimeArr: [],
				completeCountArr: [],
				alarmCountArr: [],
				yesterdayArr: [],
			});
		} else {
			ltFlag = true;
			trendScale.value = Math.ceil(resData.length / 48);
			if (trendScale.value < 10) {
				trendScale.value = 10;
			}
			const mergeData = mergeTrendData(resData, trendScale.value);
			renderChart(ltFlag, mergeData);
		}
	});
}
// 渲染趋势图
function renderChart(ltFlag: boolean, resObj: anyObj) {
	sysTrendChart.off('brushSelected');
	const yAixsIndex = ltFlag ? 0 : 1;
	const lineStyle = ltFlag ? { color: '#2beded' } : { color: 'rgba(0,0,0,0)' };
	sysTrendChart.setOption({
		// 提示框
		tooltip: {
			show: ltFlag,
			trigger: 'axis',
		},
		// 坐标系位置
		grid: {
			x: 60,
			x2: 50,
			y: 30,
			y2: 25,
		},
		// 图例标记
		legend: {
			data: [
				{
					name: '访问量',
					icon: 'roundRect',
				},
				{
					name: '告警量',
					icon: 'roundRect',
				},
				{
					name: '昨日访问量',
					icon: 'roundRect',
				},
			],
			align: 'right',
			left: 'center',
			itemWidth: 20,
			itemHeight: 12,
			itemGap: 20,
			textStyle: {
				color: '#ffffff',
			},
		},
		dataZoom: [
			{
				type: 'inside',
				start: 0,
				end: 100,
			},
		],
		toolbox: {
			iconStyle: {
				color: '#ffffff',
				borderColor: '#ffffff',
			},
			emphasis: {
				iconStyle: {
					color: '#2beded',
					borderColor: '#2beded',
					textFill: '#2beded',
				},
			},
			right: 20,
			show: true,
			feature: {
				brush: {
					type: ['lineX', 'clear'],
					title: {
						clear: '清除选择',
						lineX: '横向选择',
					},
				},
			},
		},
		brush: {
			id: 'sysChart',
			xAxisIndex: 0,
			throttleType: 'debounce',
			throttleDelay: 500,
		},
		// x轴
		xAxis: {
			type: 'category',
			data: ltFlag ? resObj.labelTimeArr : ['00:00', '01:00', '02:00'],
			boundaryGap: false,
			axisLabel: {
				show: ltFlag,
			},
			// X坐标轴样式
			axisLine: {
				lineStyle: {
					color: '#ffffff',
				},
			},
			// X轴刻度样式
			axisTick: {
				show: false,
			},
		},
		// y轴
		yAxis: [
			{
				type: 'value',
				// Y坐标轴样式
				axisLine: {
					show: false,
					lineStyle: {
						opacity: 0,
					},
				},
				// Y轴刻度样式
				axisTick: {
					show: false,
				},
				axisLabel: {
					color: '#2beded',
				},
				// 分隔线样式
				splitLine: {
					show: true,
					lineStyle: {
						color: '#ffffff',
					},
				},
			},
			{
				type: 'value',
				minInterval: 1000,
				position: 'left',
				// Y坐标轴样式
				axisLine: {
					show: !ltFlag,
					lineStyle: {
						color: '#ffffff',
					},
				},
				// Y轴刻度样式
				axisTick: {
					show: false,
				},
				// 分隔线样式
				splitLine: {
					show: false,
				},
			},
		],
		series: [
			{
				name: '访问量',
				type: 'line',
				yAxisIndex: yAixsIndex,
				data: ltFlag ? resObj.completeCountArr : [0, 1000, 2000],
				symbol: 'none',
				smooth: true,
				itemStyle: {
					color: '#2beded',
				},
				// 填充区域
				areaStyle: getAreaStyle('rgb(43, 237, 237)', 1, 0.6).areaStyle,
				lineStyle: lineStyle,
			},
			{
				name: '告警量',
				type: 'line',
				data: ltFlag ? resObj.alarmCountArr : [],
				symbol: 'none',
				smooth: true,
				yAxisIndex: 0,
				itemStyle: {
					color: '#fc5678',
				},
				// 填充区域
				areaStyle: getAreaStyle('rgb(252,86,120)', 1, 0.6).areaStyle,
			},
			{
				name: '昨日访问量',
				type: 'line',
				data: ltFlag ? resObj.yesterdayArr : [],
				symbol: 'none',
				smooth: true,
				yAxisIndex: 0,
				itemStyle: {
					color: '#ff915a',
				},
				// 填充区域
				areaStyle: getAreaStyle('rgb(255, 145, 90)', 1, 0.6).areaStyle,
			},
		],
	});
	sysTrendChart.on('brushSelected', (params: anyObj) => {
		if (params.batch[0].areas.length > 0) {
			stopRefreshInterval();
			const range = params.batch[0].areas[0].coordRange;
			if (range.length === 2) {
				const labelLength = resObj.labelTimeArr.length;
				if (range[1] >= labelLength) {
					// 区域两边滑到最右侧图外
					routeParams.tableStartTime = range[0] >= labelLength - 1 ? resObj.labelTimeArr[labelLength - 2] : resObj.labelTimeArr[range[0]];
					routeParams.tableEndTime = resObj.labelTimeArr[labelLength - 1];
				} else if (range[0] < 0) {
					// 区域两边滑到最左侧图外
					routeParams.tableStartTime = resObj.labelTimeArr[0];
					routeParams.tableEndTime = range[1] <= 0 ? resObj.labelTimeArr[1] : resObj.labelTimeArr[range[1]];
				} else {
					routeParams.tableStartTime = resObj.labelTimeArr[range[0]];
					routeParams.tableEndTime = resObj.labelTimeArr[range[1]];
				}
				// if (lastTimeRange.startTime === routeParams.tableStartTime && lastTimeRange.endTime === routeParams.tableEndTime) {
				// 	return; // 时间范围没变时不刷新表格,因为切换时间选项时,若有框选会触发这个事件
				// }
				getTableData();
			}
		} else {
			startRefreshInterval();
		}
	});
	// if (firstRender.value) {
	// 框选指定时间区域
	const startInx = resObj.labelTimeArr.indexOf(routeParams.tableStartTime);
	const endInx = resObj.labelTimeArr.indexOf(routeParams.tableEndTime);
	sysTrendChart.dispatchAction({
		type: 'brush',
		areas: [
			// 一个对象一个选框
			{
				xAxisIndex: 0,
				yAxisIndex: 'all',
				brushType: 'lineX',
				coordRange: [startInx, endInx],
			},
		],
	});
	// firstRender.value = false;
	// }
}
// 归并趋势图数据
function mergeTrendData(arr: [], scale: number) {
	const resLabelTimeArr: string[] = [],
		resCompleteCountArr: any[] = [],
		resAlarmCountArr: any[] = [],
		yesterdayCountArr: any[] = [];
	arr.forEach((r: any) => {
		resLabelTimeArr.push(r.cycleTime.substring(11, 16));
		resCompleteCountArr.push(r.visitCount);
		resAlarmCountArr.push(r.alarmCount);
		yesterdayCountArr.push(r.yesterdayCount);
	});
	return {
		labelTimeArr: resLabelTimeArr,
		completeCountArr: resCompleteCountArr,
		alarmCountArr: resAlarmCountArr,
		yesterdayArr: yesterdayCountArr,
	};
	// 为了一分钟一个刻度,当天的数据也不做归并
	/*const firstCycleTime = arr[0].cycleTime.substring(0, 19);
  const scaleUsec = scale * 60 * 1000;
  const startTime = firstCycleTime.substring(0, 10) + " 00:00:00";
  const startTimeUsec = new Date(startTime.substring(0, 19).toString().replace(/-/g, "/")).getTime();
  const endTimeUsec = startTimeUsec + 24 * 60 * 60 * 1000;  // 当天0点到啊第二天0点
  let tempTimeUsec = new Date(startTime.substring(0, 19).toString().replace(/-/g, "/")).getTime();
  const labelTimeArr = [];
  const labelTimeUsecArr = [];
  while (tempTimeUsec <= endTimeUsec) {
    labelTimeArr.push(parseTime(tempTimeUsec, "{y}-{m}-{d} {h}:{i}:{s}"));
    labelTimeUsecArr.push(tempTimeUsec);
    tempTimeUsec += scaleUsec;
  }
  let inx = 0;
  // 添加一条当前时间的数据，防止断数据时能补刻度
  arr.push({
    cycleTime: parseTime(new Date().getTime(), "{y}-{m}-{d} {h}:{i}:{s}"),
    visitCount: 0,
    alarmCount: 0,
    yesterdayCount: 0,
  });
  arr.forEach((r) => {
    const cycleTimeUsec = new Date(r.cycleTime.substring(0, 19).toString().replace(/-/g, "/")).getTime();
    while (cycleTimeUsec >= labelTimeUsecArr[inx + 1]) {
      inx++;
      resLabelTimeArr.push(parseTime(labelTimeArr[inx], "{h}:{i}"));
      resCompleteCountArr.push(0);
      resAlarmCountArr.push(0);
      yesterdayCountArr.push(0);
    }
    const formatterLabelTime = parseTime(labelTimeArr[inx], "{h}:{i}");
    if (
      resLabelTimeArr.length <= 0 ||
      resLabelTimeArr[resLabelTimeArr.length - 1] !== formatterLabelTime
    ) {
      resLabelTimeArr.push(formatterLabelTime);
      resCompleteCountArr.push(r.visitCount);
      resAlarmCountArr.push(r.alarmCount);
      yesterdayCountArr.push(r.yesterdayCount);
    } else {
      resCompleteCountArr[resLabelTimeArr.length - 1] += r.visitCount;
      resAlarmCountArr[resLabelTimeArr.length - 1] += r.alarmCount;
      yesterdayCountArr[resLabelTimeArr.length - 1] += r.yesterdayCount;
    }
  });
  // 去掉添加的数据
  arr.pop();
  // 如果刻度小于30，去掉最后一个点
  if (scale < 30 && resLabelTimeArr.length > 0 &&
    resCompleteCountArr.length > 0 && resAlarmCountArr.length > 0 && yesterdayCountArr.length > 0) {
    resLabelTimeArr.pop();
    resCompleteCountArr.pop();
    resAlarmCountArr.pop();
    yesterdayCountArr.pop();
  }
  return {
    labelTimeArr: resLabelTimeArr,
    completeCountArr: resCompleteCountArr,
    alarmCountArr: resAlarmCountArr,
    yesterdayArr: yesterdayCountArr
  };*/
}
// 请求表格数据
function getTableData() {
	lastTimeRange.startTime = routeParams.tableStartTime;
	lastTimeRange.endTime = routeParams.tableEndTime;
	tableConfig.loading = true;
	const today = parseTime(currentDate.value, '{y}-{m}-{d}');
	queryIncrementRatioList({
		...formData,
		startTime: today + ' ' + routeParams.tableStartTime + ':00',
		endTime: today + ' ' + routeParams.tableEndTime + ':00',
	}).then((res: ApiResponse) => {
		tableConfig.loading = false;
		if (res.code !== 0) {
			proxy.$modal.msgWarning(res.msg);
			return;
		}
		if (res.data) {
			tableData.value = res.data;
			tableConfig.pagination.total = res.data.length;
		} else {
			tableData.value = [];
			tableConfig.pagination.total = 0;
		}
	});
}
// 跳转至3.0业务监控详情
function goToBusiDetail(item: anyObj) {
	const today = parseTime(currentDate.value, '{y}-{m}-{d}');
	let endTime = new Date(today + ' ' + routeParams.tableEndTime + ':00').getTime();
	endTime = parseTime(endTime + 60 * 1000, '{y}-{m}-{d} {h}:{i}:{s}');
	router.push({
		path: '/business-monitor/monitor/business-detail/index',
		query: {
			systemId: item.systemId,
			businessCode: item.businessCode,
			startTime: today + ' ' + routeParams.tableStartTime + ':00',
			endTime: endTime,
		},
	});
}
// 定时器,没有框选时1分钟自动刷新趋势图
function startRefreshInterval() {
	stopRefreshInterval(); // 确保定时器已销毁
	refreshChart.value = setInterval(() => {
		getChartData();
	}, 1000 * 60);
}
// 关闭刷新定时器
function stopRefreshInterval() {
	clearInterval(refreshChart.value);
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
@import '@/styles/ops-workbench/common.scss';
@import '@/styles/ops-workbench/yd-table.scss';
.ywgzt-container {
	min-width: 1440px;
	min-height: 100vh !important;
	.content {
		margin-top: 10px;
	}
	.bg-box {
		background-color: rgba(29, 39, 75, 0.31);
		border: unset;
		border-radius: 12px;
		padding: 10px;
		margin-top: 10px;
	}
	.chart-box {
		height: 360px;
		width: 100%;
		.trend-toggle-row {
			height: 26px;
			text-align: right;
			color: #2beded;
			.trend-title {
				color: #2beded;
				font-size: 14px;
			}
			:deep(.el-select) {
				width: 88px;
				padding-left: 4px;
			}
			:deep(.el-select > .el-input) {
				display: block;
				width: 100%;
				background-color: rgba(29, 39, 75, 0.2);
			}
			:deep(.el-input--mini .el-input__inner) {
				color: #ffffff;
				font-size: 13px;
				text-align: center;
				border: 1px solid #2abcca;
				border-radius: 8px;
				background-color: transparent;
				height: 26px;
				padding-left: 10px;
			}
		}
		.chart-style {
			height: calc(100% - 26px);
			width: 100%;
		}
	}
	.table-title {
		display: flex;
		align-items: center;
	}
	.circle {
		display: inline-block;
		width: 8px;
		height: 8px;
		margin-left: 8px;
		margin-right: 8px;
		background-color: #2beded;
		border-radius: 50%;
		-moz-border-radius: 50%;
		-webkit-border-radius: 50%;
	}
	.title-label {
		color: #ffffff;
		font-size: 18px;
		font-weight: bold;
	}
}
</style>
